/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						 micro_map_window.cpp

	$Header: /heroes4/micro_map_window.cpp $

	$NoKeywords: $

 ************************************************************************/

#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "micro_map_window.h"

#include <assert.h>

#include "bitmap_layer.h"
#include "convert_16_bit.h"
#include "map_point.h"
#include "map_rect.h"
#include "paint_surface.h"

// --------------------------------------------------------------------------
// t_micro_map_renderer members
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_micro_map_renderer::t_micro_map_renderer(
	t_adventure_map const &	adventure_map,
	int						level,
	int						team_view,
	t_screen_point const &	view_size,
	t_bitmap_layer_ptr		marker_layer_ptr,
	t_map_rect_2d const &	marker_pos )
	:	t_mini_map_renderer( adventure_map, team_view ),
		m_marker_layer_ptr( marker_layer_ptr ),
		m_window_ptr( 0 )
{
	assert( m_marker_layer_ptr.get() != 0 );

	set_view_level( level );
	resize( view_size );

	t_screen_rect marker_rect =
		get_extent(
			get_tile_rect( marker_pos.top_left ),
			get_tile_rect( marker_pos.bottom_right - t_map_point_2d( 1, 1 ) ) );

	t_screen_rect const & marker_layer_rect = m_marker_layer_ptr->get_rect();

	m_marker_pos =
			marker_rect.top_left()
		+	( marker_rect.size() - marker_layer_rect.size() ) / 2
		-	marker_layer_rect.top_left();
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_micro_map_renderer::~t_micro_map_renderer()
{
	if ( m_window_ptr != 0 )
		m_window_ptr->set_renderer( 0 );
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_micro_map_renderer::t_back_buffer_ptr
t_micro_map_renderer::create_back_buffer( t_screen_point const & size )
{
	m_buffer_ptr = new t_memory_bitmap16( size.x, size.y );
	return m_buffer_ptr;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
void t_micro_map_renderer::on_rect_dirtied(
	t_screen_rect const &	dirtied_rect )
{
	if ( m_window_ptr != 0 )
		m_window_ptr->on_rect_dirtied( dirtied_rect );
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
void t_micro_map_renderer::on_view_level_changed( int level )
{
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
void t_micro_map_renderer::on_view_resized( t_screen_point const & size )
{
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
void t_micro_map_renderer::update( t_screen_rect const & rect )
{
	t_mini_map_renderer::update( rect );

	t_screen_rect marker_rect = m_marker_pos + m_marker_layer_ptr->get_rect();
	if ( intersect( marker_rect, rect ) )
	{
		marker_rect = intersection( marker_rect, rect );
		m_marker_layer_ptr->draw_to( marker_rect - m_marker_pos, *m_buffer_ptr, marker_rect.top_left() );
	}
}

// --------------------------------------------------------------------------
// t_micro_map_window members
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_micro_map_window::t_micro_map_window(
	t_screen_point const &	point,
	t_window *				parent_ptr )
	:	t_window(
			t_screen_rect( point, t_screen_point( 0, 0 ) ),
			k_no_transparency,
			parent_ptr )
{
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_micro_map_window::~t_micro_map_window()
{
	if ( m_renderer_ptr != 0 )
		set_renderer( 0 );
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
void t_micro_map_window::paint( t_paint_surface & paint_surface )
{
	if ( m_renderer_ptr != 0 )
	{
		t_screen_rect const & rect = paint_surface.get_rect();
		m_renderer_ptr->update( rect );
		paint_surface.draw( rect.top_left(), *m_renderer_ptr->m_buffer_ptr, rect );
	}
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
void t_micro_map_window::set_renderer(
	t_micro_map_renderer *	new_renderer_ptr )
{
	t_counted_ptr< t_micro_map_renderer > counted_renderer_ptr = new_renderer_ptr;

	if ( new_renderer_ptr == m_renderer_ptr )
		return;

	if ( m_renderer_ptr != 0 )
		m_renderer_ptr->m_window_ptr = 0;

	m_renderer_ptr = new_renderer_ptr;

	t_screen_point view_size;
	if ( m_renderer_ptr != 0 )
	{
		if ( m_renderer_ptr->m_window_ptr )
		{
			assert( m_renderer_ptr->m_window_ptr->m_renderer_ptr == m_renderer_ptr );
			m_renderer_ptr->m_window_ptr->set_renderer( 0 );
		}

		m_renderer_ptr->m_window_ptr = this;

		view_size = m_renderer_ptr->get_view_size();
	}
	else
		view_size = t_screen_point( 0, 0 );

	move_screen_rect( t_screen_rect( get_screen_rect().top_left(), view_size ) );

	invalidate();
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
void t_micro_map_window::on_rect_dirtied( t_screen_rect const & dirtied_rect )
{
	invalidate( dirtied_rect );
}
